﻿#include "GlobalHooks.h"
GlobalHooks* GlobalHooks::instance=nullptr;
QMutex GlobalHooks::instanceMutex;
GlobalHooks::Deleter GlobalHooks::deleter(GlobalHooks::instanceMutex);
GlobalHooks::GlobalHooks(QObject *parent)
    : QObject{parent}
{
    keyboardHook_ = SetWindowsHookEx(WH_KEYBOARD_LL, lowLevelKeyboardProc, GetModuleHandle(NULL), 0);
    mouseHook_ = SetWindowsHookEx(WH_MOUSE_LL, lowLevelMouseProc, GetModuleHandle(NULL), 0);
}

GlobalHooks::~GlobalHooks()
{
    UnhookWindowsHookEx(keyboardHook_);
    UnhookWindowsHookEx(mouseHook_);
}

LRESULT GlobalHooks::lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode == HC_ACTION) {
        if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) {
            {
                if(reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam)->vkCode==27)
                    emit GlobalHooks::getinstance()->keyPressed(wParam,lParam);
                else if(reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam)->vkCode>=48&&reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam)->vkCode<=57)
                    emit GlobalHooks::getinstance()->keyPressed(wParam,lParam);
                else if(reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam)->vkCode>=96&&reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam)->vkCode<=105)
                    emit GlobalHooks::getinstance()->keyPressed(wParam,lParam);
            }
        } else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) {
            emit GlobalHooks::getinstance()->keyReleased(wParam,lParam);
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

LRESULT GlobalHooks::lowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode == HC_ACTION) {
        switch(wParam)
        {
        case WM_LBUTTONDOWN:
            emit GlobalHooks::getinstance()->mouseLeftButtonPressed(wParam,lParam);
            break;
        case WM_LBUTTONUP:
            emit GlobalHooks::getinstance()->mouseLeftButtonReleased(wParam,lParam);
            break;
        case WM_RBUTTONDOWN:
            emit GlobalHooks::getinstance()->mouseRightButtonPressed(wParam,lParam);
            break;
        case WM_RBUTTONUP:
            emit GlobalHooks::getinstance()->mouseRightButtonReleased(wParam,lParam);
            break;
        default:
            break;
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

GlobalHooks*& GlobalHooks::getinstance()
{
    if(instance==nullptr)
    {
        QMutexLocker locker(&instanceMutex);
        if(instance==nullptr)
            instance=new GlobalHooks();
    }
    return instance;
}

GlobalHooks::Deleter::Deleter(QMutex &Mutex):deleterMutex(Mutex)
{

}

GlobalHooks::Deleter::~Deleter()
{
    QMutexLocker locker(&deleterMutex);
    if(GlobalHooks::instance!=nullptr)
    {
        delete GlobalHooks::instance;
        GlobalHooks::instance=nullptr;
    }
}
